package com.lcz.manage.util.executor;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;

import com.lcz.manage.util.exception.CCException;

import lombok.extern.slf4j.Slf4j;

/**
 * 表达式解析器
 *
 * @author lucz@yunrong.cn
 * @version V3.0
 * @date 2021/9/26 16:39
 */
@Slf4j
public class ParserEngine {

    private static final ExpressionParser EXPRESSION_PARSER;

    private static final ScriptEngineManager SCRIPT_ENGINE_MANAGER;

    static {
        EXPRESSION_PARSER = new SpelExpressionParser();
        SCRIPT_ENGINE_MANAGER = new ScriptEngineManager();
    }

    private ParserEngine() {
    }

    public static Boolean check(String formula, LinkedHashMap<String, Object> paramMaps) {
        Objects.requireNonNull(formula);
        Objects.requireNonNull(paramMaps);
        for (Map.Entry<String, Object> paramMap : paramMaps.entrySet()) {
            formula = formula.replaceAll(paramMap.getKey(), String.valueOf(paramMap.getValue()));
        }
        try {
            Expression expression = EXPRESSION_PARSER.parseExpression(formula);
            return expression.getValue(Boolean.class);
        } catch (Exception e) {
            throw new CCException("expression parse error", e);
        }
    }

    public static Object eval(String formula, LinkedHashMap<String, Object> paramMaps) {
        Objects.requireNonNull(formula);
        Objects.requireNonNull(paramMaps);
        for (Map.Entry<String, Object> paramMap : paramMaps.entrySet()) {
            formula = formula.replaceAll(paramMap.getKey(), String.valueOf(paramMap.getValue()));
        }
        ScriptEngine engine = SCRIPT_ENGINE_MANAGER.getEngineByName("js");
        try {
            return engine.eval(formula);
        } catch (ScriptException e) {
            throw new CCException("scriptEngine eval error", e);
        }
    }

}
